<template>
    <div
        class="file-explorer relative w-full h-full flex flex-col border border-solid border-gray-100 mr-1"
        ref="fileExplorerDomRef"
    >
        <div class="tool-bar py-1">
            <div class="flex items-center">
                <!-- 上一级目录 -->
                <ElButton class="mx-1 !px-2" icon="top" @click="goUp" text />
                <!-- 地址输入框 -->
                <div class="flex-1 overflow-hidden">
                    <div
                        v-if="!isInputing"
                        class="bg-slate-50 rounded p-1 px-2 text-slate-600 cursor-pointer flex justify-between items-center"
                        @click="isInputing = true"
                    >
                        <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap">
                            {{ basename(currentFolder.inputingPath) }}
                        </div>
                        <el-popover :width="400">
                            <template #reference>
                                <div
                                    size="small"
                                    icon="delete"
                                    class="border border-solid border-slate-200 border-opacity-50 bg-opacity-50 px-2 py-0.5 rounded flex justify-center items-center hover:bg-slate-100"
                                >
                                    <el-icon>
                                        <Sort />
                                    </el-icon>
                                </div>
                            </template>
                            <SortConditionsEdit
                                :default-conditions="props.defaultSortConditions"
                                @change="handleSortConditionsChange"
                            />
                        </el-popover>
                    </div>
                    <!-- 路径输入框 -->
                    <ElInput
                        v-else
                        v-model="currentFolder.inputingPath"
                        @keypress.enter="goTo"
                        @blur="isInputing = false"
                        @keypress.esc="isInputing = false"
                    />
                </div>
                <!-- 刷新 -->
                <ElButton class="!mx-1 !px-2" icon="refresh" @click="readFolderAndShow(currentFolder.path)" text />
            </div>
            <div class="flex"></div>
        </div>
        <div class="list-container flex-1 overflow-hidden flex flex-col">
            <div class="list-title"></div>
            <div
                @mousedown="handleMousedown"
                class="list-content flex-1 overflow-y-auto overflow-x-hidden"
                ref="listContentDomRef"
                :data-path="currentFolder.path"
                v-droppable="filesVDroppable"
            >
                <el-scrollbar ref="listScrollDomRef">
                    <FileItem
                        v-for="item in currentFolder.showFiles"
                        :key="item.name"
                        :file-explorer-id="fileExplorerId"
                        :file="item"
                        :isSelected="currentFolder.selectedFiles.includes(item.name)"
                        @click="selectSingleFile(item)"
                        @dblclick="openFileOrDir(item)"
                        @rename="handleRename"
                        @delete="handleDelete"
                    />
                </el-scrollbar>
            </div>
            <div class="status-bur pt-1 text-xs text-slate-600">{{ currentFolder.showFiles.length }}个文件</div>
        </div>
        <!-- <div
            class=""
            ref="selectBoxDomRef"
        ></div> -->
    </div>
</template>

<script setup lang="ts">
import { basename } from '@/appUtils/path'
import { process } from '@/appUtils/process'
import { useSelectable } from '@/hooks/useSelectable'
import { keyboard } from '@/utils/keyboardAndMouse'
import { randomStr } from '@/utils/random'
import { ElScrollbar } from 'element-plus'
import { onUnmounted, ref, toRaw, useTemplateRef } from 'vue'
import { DragDataType } from '../DragAndDrop/DragDataTypes'
import { useDrag } from '../DragAndDrop/useDrag'
import { vDroppable } from '../DragAndDrop/vDroppable'
import FileItem from './components/FileItem.vue'
import SortConditionsEdit from './components/SortConditionsEdit.vue'
import { filesVDroppable, updateMouseText } from './utils/dropHandlers'
import { removeFileExplorerInstance, setFileExplorerInstance } from './utils/instances'
import { defaultSortConditions } from './utils/sortAndFilter'
import { IFileExplorerProps, useCurrentFolder } from './utils/useCurrentFolder'

const _props = withDefaults(defineProps<IFileExplorerProps>(), {
    defaultPath: process?.env?.HOME || './',
    defaultSortConditions: () => defaultSortConditions,
    watch: false
})
const props = toRaw(_props)

// 生成一个id
const fileExplorerId = randomStr(6)

// 当前文件列表
const {
    currentFolder,
    openFileOrDir,
    selectSingleFile,
    goUp,
    goTo,
    handleRename,
    handleDelete,
    highlightFile,
    readFolderAndShow,
    handleSortConditionsChange
} = useCurrentFolder(props)

// 是否正在输入目录
const isInputing = ref(false)

// 列表dom
const listContentDomRef = useTemplateRef('listContentDomRef')
const listScrollDomRef = useTemplateRef<InstanceType<typeof ElScrollbar> | null>('listScrollDomRef')

// 框选
const { selectStart } = useSelectable({
    container: listContentDomRef,
    selectableSelector: '.file-item',
    onSelectedChange: (selected) => {
        currentFolder.selectedFiles = selected.map((item) => item.dataset.filename!)
    },
    registerContainerMousedown: false
})

// mousedown处理
const handleMousedown = (e: MouseEvent) => {
    let fileItemTarget = e.target as HTMLElement
    if (fileItemTarget.tagName === 'INPUT') return
    // 查找文件项
    while (
        fileItemTarget &&
        !fileItemTarget.classList.contains('file-item') &&
        fileItemTarget !== listContentDomRef.value
    ) {
        fileItemTarget = fileItemTarget.parentElement!
    }
    const filename = fileItemTarget.dataset.filename
    // 如果鼠标按下去的地方是已经被选中，则触发拖拽，否则框选
    if (filename && currentFolder.selectedFiles.includes(filename)) {
        const selectedFiles = currentFolder.files.filter((file) => currentFolder.selectedFiles.includes(file.name))
        const updateMouseTxt = () => updateMouseText(selectedFiles)
        const { dragStart } = useDrag(
            {
                type: DragDataType.FileList,
                data: selectedFiles
            },
            {
                onDragStart: () => {
                    keyboard.on('pressingChange', updateMouseTxt)
                },
                onDragEnd: () => {
                    keyboard.off('pressingChange', updateMouseTxt)
                }
            }
        )
        dragStart()
    } else {
        selectStart(e)
    }
}

const highlightFileInComponent = async (filePath: string, ignoreScroll = false) => {
    const index = await highlightFile(filePath)
    if (ignoreScroll) return
    setTimeout(() => {
        const fileItemDom = listContentDomRef.value?.querySelector('.file-item')
        if (!fileItemDom || !index) {
            return
        }
        const unitHeight = fileItemDom.clientHeight
        const top = index * unitHeight
        console.log(listScrollDomRef.value)
        listScrollDomRef.value?.scrollTo(0, top)
    }, 300)
}

const exposeObj = {
    highlightFile: highlightFileInComponent
}

// 暴露外部方法
defineExpose(exposeObj)
// 保存实例
setFileExplorerInstance(fileExplorerId, exposeObj)

onUnmounted(() => {
    removeFileExplorerInstance(fileExplorerId)
})
</script>

<style scoped></style>
